#include <jni.h>
#include <string>
#include "facecat/stdafx.h"
#include "AndroidPaint.h"
#include "AndroidHost.h"
#include "DataCenter.h"
#include "facecat/FCUIXml.h"
#include "MainFrame.h"

HashMap<String, String> m_keyValues;
String m_textBoxRect;
String m_textBoxBackColor;
String m_textBoxColor;
String m_textBoxBorderColor;
String m_textBoxState;
String m_textBoxName;
String m_textBoxContent;
String m_textBoxFont;
String m_lastCppName;

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_getTextInfo(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";

    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    lstring ssCmd = strCmd;
    if(ssCmd == "rect"){
        resStr = FCTran::StringTostring(m_textBoxRect);
    }else if(ssCmd == "backcolor"){
        resStr = FCTran::StringTostring(m_textBoxBackColor);
    }else if(ssCmd == "color"){
        resStr = FCTran::StringTostring(m_textBoxColor);
    }else if(ssCmd == "bordercolor"){
        resStr = FCTran::StringTostring(m_textBoxBorderColor);
    }else if(ssCmd == "state"){
        resStr = FCTran::StringTostring(m_textBoxState);
    }else if(ssCmd == "name"){
        resStr = FCTran::StringTostring(m_textBoxName);
    }else if(ssCmd == "text"){
        resStr = FCTran::StringTostring(m_textBoxContent);
    }else if(ssCmd == "font"){
        resStr = FCTran::StringTostring(m_textBoxFont);
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_setTextInfo(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    lstring ssCmd = strCmd;
    String text = FCTran::stringToString(ssCmd);
    FCNative *native = AndroidHost::getNativeCpp(m_lastCppName);
    if(native){
        FCView *view = native->findView(m_textBoxName);
        view->setText(text);
        view->invalidate();
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_createNative(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    FCNative *native = new FCNative();
    AndroidPaint *paint = new AndroidPaint();
    paint->m_native = native;
    AndroidHost *host = new AndroidHost;
    host->m_env = env;
    native->setHost(host);
    host->setNative(native);
    native->setPaint(paint);
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String cppName = FCTran::stringToString(strCmd);
    AndroidHost::addNativeCpp(cppName, native);
    host->m_cppName = cppName;
    FCSize nativeSize = {500, 1000};
    native->setSize(nativeSize);
    String xmlStr = m_keyValues.get(L"mainframe");
    DataCenter::startService();
    DataCenter::startConnect();
    MainFrame *xml = new MainFrame();
    xml->setNative(native);
    xml->loadXml(xmlStr, 0);
    return env->NewStringUTF(FCTran::StringTostring((FCTran::intToStr(DataCenter::getLatestServiceClient()->getSocketID())).c_str()));
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_setKeyValue(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";

    char strCmd[1024000] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String strInput = FCTran::stringToString(strCmd);
    int idx = (int)strInput.find(L",");
    String left = strInput.substr(0, idx);
    String right = strInput.substr(idx + 1);
    m_keyValues.put(left, right);
    resStr = FCTran::StringTostring(right);
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_deleteNative(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String cppName = FCTran::stringToString(strCmd);
    FCNative *native = AndroidHost::getNativeCpp(cppName);
    if(native){
        AndroidHost *androidHost = (AndroidHost*)native->getHost();
        androidHost->m_env = env;
        AndroidHost::removeNativeCpp(cppName);
        delete native;
        native = 0;
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_updateNative(JNIEnv* env, jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String wCmd = FCTran::stringToString(strCmd);
    ArrayList<String> strs = FCTran::split(wCmd, L",");
    String cppName = strs.get(0);
    FCNative *native = AndroidHost::getNativeCpp(cppName);
    if(native){
        int cx = FCTran::strToInt(strs.get(1));
        int cy = FCTran::strToInt(strs.get(2));
        AndroidHost *androidHost = (AndroidHost*)native->getHost();
        androidHost->m_env = env;
        int cx2 = FCTran::strToInt(strs.get(3));
        int cy2 = FCTran::strToInt(strs.get(4));
        int state = FCTran::strToInt(strs.get(5));
        if(state == 1){
            native->setAllowScaleSize(true);
        }else{
            native->setAllowScaleSize(false);
        }
        FCSize clientSize = {cx2, cy2};
        FCSize newSize = {cx, cy};
        androidHost->m_clientSize = clientSize;
        native->setScaleSize(newSize);
        native->setSize(clientSize);
        native->update();
        resStr = FCTran::StringTostring(FCTran::sizeToStr(native->getSize()));
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_onPaint(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String cppName = FCTran::stringToString(strCmd);
    FCNative *native = AndroidHost::getNativeCpp(cppName);
    if(native){
        AndroidPaint *paint = (AndroidPaint*)native->getPaint();
        AndroidHost *androidHost = (AndroidHost*)native->getHost();
        androidHost->m_env = env;
        FCRect drawRect = {0};
        androidHost->onPaint(drawRect);
        ArrayList<NativeCmd> commands = paint->m_commands;
        resStr = NativeCmd::commandsToStr(&commands);
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_onTouchBegin(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    m_textBoxState = L"";
    String wCmd = FCTran::stringToString(strCmd);
    ArrayList<String> strs = FCTran::split(wCmd, L"|");
    String cppName = strs.get(0);
    FCNative *native = AndroidHost::getNativeCpp(cppName);
    if(native){
        bool firstTouch = FCTran::strToBool(strs.get(1));
        FCPoint firstPoint = FCTran::strToPoint(strs.get(2));
        bool secondTouch = FCTran::strToBool(strs.get(3));
        FCPoint secondPoint = FCTran::strToPoint(strs.get(4));
        int clicks = FCTran::strToInt(strs.get(5));
        FCPoint touchPoint = FCTran::strToPoint(strs.get(6));
        AndroidHost *androidHost = (AndroidHost*)native->getHost();
        androidHost->m_env = env;
        androidHost->m_touchPoint = touchPoint;
        FCTouchInfo touchInfo;
        touchInfo.m_firstTouch = firstTouch;
        touchInfo.m_secondTouch = secondTouch;
        touchInfo.m_firstPoint = firstPoint;
        touchInfo.m_secondPoint = secondPoint;
        touchInfo.m_clicks = clicks;
        FCView *oldFocusedView = native->getFocusedView();
        native->onTouchBegin(touchInfo);
        FCView *newFocusedView = native->getFocusedView();
        if(newFocusedView && dynamic_cast<FCTextBox*>(newFocusedView)){
            FCRect displayRect = {native->clientX(newFocusedView), native->clientY(newFocusedView), 0, 0};
            displayRect.right = displayRect.left + newFocusedView->getSize().cx;
            displayRect.bottom = displayRect.top + newFocusedView->getSize().cy;
            m_textBoxRect = FCTran::rectToStr(displayRect);
            m_textBoxBackColor = FCTran::colorToStr(newFocusedView->getBackColor());
            m_textBoxColor = FCTran::colorToStr(newFocusedView->getTextColor());
            m_textBoxBorderColor = FCTran::colorToStr((newFocusedView->getBorderColor()));
            m_textBoxName = newFocusedView->getName();
            m_textBoxState = L"show";
            m_textBoxContent = newFocusedView->getText();
            m_textBoxFont = FCTran::fontToStr(newFocusedView->getFont());
            m_lastCppName = cppName;
        }else{
            if(oldFocusedView && dynamic_cast<FCTextBox*>(oldFocusedView)){
                m_textBoxState = L"hide";
                m_textBoxName = oldFocusedView->getName();
            }
        }
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_onTouchMove(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String wCmd = FCTran::stringToString(strCmd);
    ArrayList<String> strs = FCTran::split(wCmd, L"|");
    String cppName = strs.get(0);
    FCNative *native = AndroidHost::getNativeCpp(cppName);
    if(native){
        bool firstTouch = FCTran::strToBool(strs.get(1));
        FCPoint firstPoint = FCTran::strToPoint(strs.get(2));
        bool secondTouch = FCTran::strToBool(strs.get(3));
        FCPoint secondPoint = FCTran::strToPoint(strs.get(4));
        int clicks = FCTran::strToInt(strs.get(5));
        FCPoint touchPoint = FCTran::strToPoint(strs.get(6));
        AndroidHost *androidHost = (AndroidHost*)native->getHost();
        androidHost->m_env = env;
        androidHost->m_touchPoint = touchPoint;
        FCTouchInfo touchInfo;
        touchInfo.m_firstTouch = firstTouch;
        touchInfo.m_secondTouch = secondTouch;
        touchInfo.m_firstPoint = firstPoint;
        touchInfo.m_secondPoint = secondPoint;
        touchInfo.m_clicks = clicks;
        native->onTouchMove(touchInfo);
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_onTouchEnd(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String wCmd = FCTran::stringToString(strCmd);
    ArrayList<String> strs = FCTran::split(wCmd, L"|");
    String cppName = strs.get(0);
    FCNative *native = AndroidHost::getNativeCpp(cppName);
    if(native){
        bool firstTouch = FCTran::strToBool(strs.get(1));
        FCPoint firstPoint = FCTran::strToPoint(strs.get(2));
        bool secondTouch = FCTran::strToBool(strs.get(3));
        FCPoint secondPoint = FCTran::strToPoint(strs.get(4));
        int clicks = FCTran::strToInt(strs.get(5));
        FCPoint touchPoint = FCTran::strToPoint(strs.get(6));
        AndroidHost *androidHost = (AndroidHost*)native->getHost();
        androidHost->m_env = env;
        androidHost->m_touchPoint = touchPoint;
        FCTouchInfo touchInfo;
        touchInfo.m_firstTouch = firstTouch;
        touchInfo.m_secondTouch = secondTouch;
        touchInfo.m_firstPoint = firstPoint;
        touchInfo.m_secondPoint = secondPoint;
        touchInfo.m_clicks = clicks;
        native->onTouchEnd(touchInfo);
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_onTimer(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String cppName = FCTran::stringToString(strCmd);
    FCNative *native = AndroidHost::getNativeCpp(cppName);
    if(native){
        AndroidHost *androidHost = (AndroidHost*)native->getHost();
        androidHost->m_env = env;
        androidHost->onTimer();
    }
    return env->NewStringUTF(resStr.c_str());
}

extern "C" JNIEXPORT jstring JNICALL
Java_topin_facecat_MainActivity_setUserPath(
        JNIEnv* env,
        jclass, jstring cmd) {
    lstring resStr = "";
    char strCmd[1024] = {0};
    if(env->GetStringUTFLength(cmd) > 0){
        AndroidHost::JstringToString(strCmd, env, cmd);
    }
    String userPath = FCTran::stringToString(strCmd);
    //DataCenter::setUserPath(userPath);
    return env->NewStringUTF(resStr.c_str());
}